package util

import (
	"crypto/aes"
	"crypto/md5"
	"crypto/sha1"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"github.com/andreburgaud/crypt2go/ecb"
	"io/ioutil"
	"likeadmin/model/client"
	"log"
	"net/http"
	"strconv"
	"strings"
	"time"
)

// OppoCallbackUtil OPPO回传工具类
type OppoCallbackUtil struct{}

// UploadOppo OPPO付费回传
func (o OppoCallbackUtil) UploadOppo(reportdata map[string]interface{}) string {
	// 构建加桌激活数据
	millisecond := o.getMillisecond()
	postData := o.buildOppoPostData(reportdata, millisecond)

	// 执行上报
	postDataJSON, _ := json.Marshal(postData)
	signature := fmt.Sprintf("%x", md5.Sum([]byte(fmt.Sprintf("%s%d%s", string(postDataJSON), millisecond, "e0u6fnlag06lc3pl"))))

	url := "https://api.ads.heytapmobi.com/api/uploadActiveData"
	result := o.httpPost(url, string(postDataJSON), map[string]string{
		"Content-Type": "application/json",
		"signature":    signature,
		"timestamp":    fmt.Sprintf("%d", millisecond),
	})

	if o.isJSON(result) {
		var resultData map[string]interface{}
		json.Unmarshal([]byte(result), &resultData)
		if retCode, ok := resultData["ret"].(float64); ok && retCode == 0 {
			log.Printf("Oppo回调处理成功: id=%v, result=%+v", reportdata["id"], resultData)
			return fmt.Sprintf("Oppo回调处理成功: id=%v::success", reportdata["id"])
		} else {
			log.Printf("Oppo回调处理失败: id=%v, result=%+v", reportdata["id"], resultData)
			return fmt.Sprintf("Oppo回调处理失败: id=%v::error", reportdata["id"])
		}
	} else {
		log.Printf("Oppo回调处理失败-非json: id=%v", reportdata["id"])

		return fmt.Sprintf("Oppo回调处理失败-非json: id=%v::error", reportdata["id"])
	}
}

// BuildOppoPostData 构建OPPO上报数据
func (o OppoCallbackUtil) buildOppoPostData(callbackInfo map[string]interface{}, timestamp int64) map[string]interface{} {
	if timestamp == 0 {
		timestamp = time.Now().UnixNano() / 1e6 // 转换为毫秒
	}

	dataType := callbackInfo["dataType"]

	postData := map[string]interface{}{
		"dataType":    dataType,
		"timestamp":   timestamp,
		"channel":     1, // 1=OPPO
		"ascribeType": 1, // 1=广告主归因
		"appType":     3, // 3=快应用
		"clientIp":    callbackInfo["ip"],
		"pkg":         callbackInfo["package_name"], // 需要根据渠道获取包名或快应用ID
	}

	// 设备信息
	if imei, ok := callbackInfo["imei"]; ok && imei != "" {
		postData["imei"] = o.aesEncrypt(imei.(string), "XGAXicVG5GMBsx5bueOe4w==")
		postData["type"] = 1
	} else if oaid, ok := callbackInfo["oaid"]; ok && oaid != "" {
		postData["ouId"] = o.aesEncrypt(oaid.(string), "XGAXicVG5GMBsx5bueOe4w==")
		postData["type"] = 0
	}

	// 支付金额（支付回传时使用）
	// 快应用付费
	if dataType == 16 {
		if totalFee, ok := callbackInfo["money"]; ok {
			if fee, err := strconv.Atoi(fmt.Sprintf("%v", totalFee)); err == nil {
				postData["money"] = fee // 单位：分
			}
		}
	}

	return postData
}

// HttpPost HTTP POST请求工具函数
func (o OppoCallbackUtil) httpPost(url string, data string, headers map[string]string) string {
	client := &http.Client{
		Timeout: 30 * time.Second,
	}

	req, _ := http.NewRequest("POST", url, strings.NewReader(data))

	// 设置headers
	for key, value := range headers {
		req.Header.Set(key, value)
	}

	resp, err := client.Do(req)
	if err != nil {
		return ""
	}
	defer resp.Body.Close()

	body, _ := ioutil.ReadAll(resp.Body)
	return string(body)
}

// GetMillisecond 获取毫秒时间戳
func (o OppoCallbackUtil) getMillisecond() int64 {
	return time.Now().UnixNano() / 1e6
}

// AesEncrypt AES加密 (使用第三方ECB库)
func (o OppoCallbackUtil) aesEncrypt(input string, base64Key string) string {
	// 解码base64密钥
	key, err := base64.StdEncoding.DecodeString(base64Key)
	if err != nil {
		return ""
	}

	// 创建AES密码块
	block, err := aes.NewCipher(key)
	if err != nil {
		return ""
	}

	// 使用AES-128-ECB模式加密
	blockSize := block.BlockSize()
	// 填充输入数据
	padding := blockSize - len(input)%blockSize
	padtext := strings.Repeat(string([]byte{byte(padding)}), padding)
	input = input + padtext

	// ECB加密
	mode := ecb.NewECBEncrypter(block)
	ciphertext := make([]byte, len(input))
	mode.CryptBlocks(ciphertext, []byte(input))

	// 返回base64编码的结果
	return base64.StdEncoding.EncodeToString(ciphertext)
}

func (o OppoCallbackUtil) isJSON(s string) bool {
	var js map[string]interface{}
	return json.Unmarshal([]byte(s), &js) == nil
}

const OppoUrlPrefix = "https://sapi.ads.heytapmobi.com"

// AdData 广告汇总数据查询-子客户
func (o OppoCallbackUtil) AdData(account client.Account, day string, timeLevel string) (uint, error) {

	url := OppoUrlPrefix + "/v3/data/common/summary/queryAdData" // 需要替换为实际的URL前缀

	data := map[string]interface{}{
		"beginTime": day,
		"endTime":   day,
		//"timeLevel": "HOUR",
		"timeLevel": timeLevel,
		"paraMap": map[string]interface{}{
			"filter_zero": 1,
		},
	}
	var e error
	// 生成token
	token := o.generate(account.AccountNumber, account.UserAccount, account.ButlerAccount)

	// 序列化数据
	jsonData, err := json.Marshal(data)
	if err != nil {
		e = fmt.Errorf("序列化数据失败: %v - AccountId： %v", err, account.AccountId)
		return 0, e
	}

	// 发送HTTP请求
	headers := map[string]string{
		"Content-Type":  "application/json",
		"Authorization": "Bearer " + token,
	}

	resStr := o.httpPost(url, string(jsonData), headers)

	if resStr == "" {
		e = fmt.Errorf("请求失败: %v", account.AccountId)
		return 0, e
	}

	// 解析响应
	var res map[string]interface{}
	err = json.Unmarshal([]byte(resStr), &res)
	if err != nil {
		e = fmt.Errorf("请求失败: %v - AccountId:%v", err, account.AccountId)
		return 0, e
	}

	if res == nil {
		e = fmt.Errorf("响应为空: %v", account.AccountId)
		return 0, e
	}

	// 检查code是否为0表示成功
	if code, ok := res["code"].(float64); !ok || code != 0 {
		e = fmt.Errorf("获取oppo成本失败，错误码: %v", code)
		return 0, e
	}

	// 检查data是否存在
	data2, _ := res["data"].(map[string]interface{})

	// 更安全的成本值处理
	costValue, exists := data2["cost"]
	if !exists || costValue == nil {
		e = fmt.Errorf("cost field missing or null %v", account.AccountId)
		return 0, e
	}

	var cost uint
	switch v := costValue.(type) {
	case float64:
		if v < 0 {
			cost = 0
		} else {
			cost = uint(v)
		}
	case int:
		if v < 0 {
			cost = 0
		} else {
			cost = uint(v)
		}
	case uint:
		cost = v
	case string:
		// 尝试从字符串解析
		if parsed, err := strconv.ParseUint(v, 10, 32); err == nil {
			cost = uint(parsed)
		} else {
			e = fmt.Errorf("cannot parse cost string '%s': %v AccountId %v", v, err, account.AccountId)
			return 0, e
		}
	default:
		e = fmt.Errorf("unexpected cost type: %T, value: %v AccountId %v", costValue, costValue, account.AccountId)
		return 0, e
	}

	if cost == 0 {
		fmt.Println(fmt.Sprintf("获取到成本:cost %v  account%v", cost, account.AccountId))
	}

	return cost, nil
}

// generate 生成token的方法(需要根据实际逻辑实现)

// generate 生成token
func (o OppoCallbackUtil) generate(accountNumber, clientID, secret string) string {
	// 获取当前时间戳
	timeStamp := time.Now().Unix()

	// 构造签名字符串 (sha1(apiId.apiKey.time))
	signStr := fmt.Sprintf("%s%s%d", clientID, secret, timeStamp)
	sign := fmt.Sprintf("%x", sha1.Sum([]byte(signStr)))

	// 构造token (base64_encode(ownerId .','. apiId .','. time .','. sign))
	tokenStr := fmt.Sprintf("%s,%s,%d,%s", accountNumber, clientID, timeStamp, sign)
	token := base64.StdEncoding.EncodeToString([]byte(tokenStr))

	return token
}

// Account 账户结构体定义(需要根据实际数据库表结构调整)
type Account struct {
	AccountNumber string
	ClientID      string
	Secret        string
}
